import config
import jsontemplate
import requests
import json
import simplejson

'''
Functions below keeps the variables in the config file consistent with new actions such as updated budget, added search etc.
'''

# code for more-formatters altered from test code at https://code.google.com/p/json-template/source/browse/python/examples/reusing_the_inside.py
class MoreFormatters(object):
  def LookupWithType( self, user_str):
    # Recognize decimal string formatting
    if user_str.startswith('%'):
      return (lambda x: user_str % x), None, jsontemplate.SIMPLE_FUNC
    else:
      return None, None, None

def update_search(str):
 config.search = str
 return 0

def update_budget(bud):
 config.budget = bud
 return 0

def add_data(req):
 config.data.append(req)
 return 0

def clear_data():
 config.data.pop()
 return 0

def read_input(file_name):
 template =  open(file_name, "r")
 if file_name == 'indext.txt':
  config.ts_1 = template.read()
 else:
  config.ts_2 = template.read()

def read_to_template1(str):
 config.t1 = jsontemplate.FromString(config.ts_1, more_formatters=MoreFormatters())
 return 0

def read_to_template2(str):
 config.t2 = jsontemplate.FromString(config.ts_2, more_formatters=MoreFormatters())
 return 0

def add_total(price):
 if (price == 'null'):
  config.totalPrice = config.totalPrice + 0.00
 else:
  config.totalPrice = config.totalPrice + float(price)
 return 0

def sub_total(price):
 if (price == 'null'):
  config.totalPrice = config.totalPrice - 0.00
 else: 
  config.totalPrice = config.totalPrice - float(price)
 return 0

def reset_total():
 config.totalPrice = 0
 return 0

def removeSelect(searchterm):
 config.selectedItems.pop(searchterm, None)
 if searchterm in config.selectedItems:
   del config.selectedItems[searchterm]
 if len(config.selectedItems)==0:
  config.totalPrice=0
 return 0
  
def search_items(term):
 if term not in config.selectedItems:
  return True
 else:
  return False

def add_id(itm, term):
 if term not in config.selectedItems:
  config.selectedItems[term] = {}
  config.selectedItems[term]['id'] = itm
 else:
  config.selectedItems[term]['id'] = itm
 return 0

def add_price(price, term):
 config.selectedItems[term]['price'] = price
 return 0

def get_price(term):
 price = config.selectedItems[term]['price']
 return price

'''
recommend function returns recommendations on how much user should spend on each unselected items based on their budget and prices of that product.
It calls helper functions which are getRecPrice, getClicked, getMeanItmPrice and getTotalMean.

'''

def selections(savedItm,data):
 recdict = {}

 for x in data:
  recdict[x['searchterm']]=selectionsHelper(x['searchterm'],x, savedItm,data)
 #return full dictionary {'a':"empty", 'b':"empty",'c':"17.66", 'd':"2.99", ...}
 return recdict

# x = {'searchterm':apple, 'results':{..},{..},.., 'errors':.., 'info':..}
def selectionsHelper(searchterm,x,savedItm,data):
 if searchterm in savedItm:
  return getClicked(data,searchterm,savedItm)
 else:
  return ""



def recommend(budget,savedItm,data):
 recdict = {}
 totalspent = 0.00
 for key,value in savedItm.items():
  #handles case when user selects a item with no price
  if (value['price'] != 'null'):
   totalspent += float(value['price'])
 leftbudget = float(budget)-totalspent
 for x in data:
  recdict[x['searchterm']]=getRecPrice(x['searchterm'],x, savedItm,data,leftbudget)
 #return full dictionary {'a':"empty", 'b':"empty",'c':"17.66", 'd':"2.99", ...}
 return recdict

# x = {'searchterm':apple, 'results':{..},{..},.., 'errors':.., 'info':..}
def getRecPrice(searchterm,x,savedItm,data,leftbudget):
 if searchterm in savedItm:
  return getClicked(data,searchterm,savedItm)
 else:
  meanItmPrice = getMeanItmPrice(x)
  totalMean = getTotalMean(data,savedItm)
  if (meanItmPrice != "nothing found") and (meanItmPrice is not None) and (meanItmPrice is not 'null') and (totalMean>0.00):
   if (float(meanItmPrice)*float(leftbudget)/float(totalMean))<0:
    return 0.00
   else: 
    return "%.2f" % (float(meanItmPrice)*float(leftbudget)/float(totalMean))
  else:
   return "0.00"

def getClicked(data,searchterm,savedItm):
 for key,value in savedItm.items():
  if key==searchterm:
   idOfItm = savedItm[searchterm]['id']
 for x in data:
  for result in x['results']:
   if idOfItm == result['id']:
    if 'best_page' in result:
     return result['title']+" <br/> "+"$"+str(result['best_page']['price'])
 return "error"

def getMeanItmPrice(x):
 pricelist = []
 resultslist = x['results']
 for result in resultslist:
  if 'best_page' in result:
   pricelist.append(result['best_page']['price'])
 sortedpricelist = sorted(pricelist)
 if len(sortedpricelist)<1:
  return "nothing found"
 return sortedpricelist[int(len(pricelist)/2)]


def getTotalMean(data,savedItm):
 total = 0.00
 for k in data:
  if k['searchterm'] not in savedItm:
   if (getMeanItmPrice(k) != "nothing found") and (getMeanItmPrice(k) is not None) and (getMeanItmPrice(k) is not 'null'):
    total += float(getMeanItmPrice(k))
 return total

def getRangePercentage(x,recprice):
 pricelist = []
 resultslist = x['results']
 for result in resultslist:
  if 'best_page' in result:
   pricelist.append(result['best_page']['price'])
 sortedpricelist = sorted(pricelist)
 count=0.00
 for n in sortedpricelist:
  if float(recprice)>float(n):
   count +=1.00
 if float(len(sortedpricelist)) !=0:
  return float(count)/float(len(sortedpricelist))*100.00
 else:
  return 0.00

'''
budgetWarningLevel function returns a color(one of red,orange,clear,yellow, and green) to indicate whether remaining budget is enough to buy remaining unselected products with a reasonable price. It will calculate the median price of each unselected items, and compare it with the budget left, and return a color.

red:remaining budget can only let you buy unselected items of price range in low 20 percent
orange:remaining budget can only let you buy unselected items of price range in low 40 percent
clear: remaining budget can let you buy unselected items of price around median price
yellow: remaining budget allows you to buy unselected items of price in high 80 percent
green: remaining budget allows you to buy unselected items of price in high 100 percent

'''

def budgetWarningLevel(budget,savedItm,data):
 recList = recommend(budget,savedItm,data)
 for key, value in recList.items():
  if value =="empty":
   del recList[key]

 if len(savedItm) == len(config.data):
  if config.budget > config.totalPrice:
   return "green"
  elif config.budget < config.totalPrice:
   return "red"
  else:
   return "clear"

 percentageList = {}
 for key,value in recList.items():
  for x in data:
   if key==x['searchterm'] and (key not in savedItm):
    percentageList[key]=getRangePercentage(x,float(value))
 
 #average the percentages
 totalPercent = 0.00
 if len(percentageList)>0:
  for key,value in percentageList.items():
   totalPercent += value
  avgPercent = totalPercent/len(percentageList) 
 else:
  avgPercent=50
 if 0<=avgPercent and avgPercent<20:
  return "red"

 elif 21<=avgPercent and avgPercent<40:
  return "orange"
 
 elif 41<=avgPercent and avgPercent<60:
  return "clear"
 
 elif 61<=avgPercent and avgPercent<80:
  return "yellow"
 
 elif 81<=avgPercent and avgPercent<=100:
  return "green"

 else:
  return "errrrrrrrrrror"
